//============================================================================
// Name        : surface.cpp
// Author      : dfoelber
//============================================================================

#include "graphics/surface.h"
#include "SDL/SDL_rotozoom.h"
#include <iostream>

using namespace std;

/**
* Default constructor
**/
Surface::Surface()
{
	surface = NULL;
}

/**
* Constructor
* 
* @param surface An SDL surface to wrap.
**/
Surface::Surface( SDL_Surface* surface )
{
	this->surface = surface;
}

/**
* Deconstructor
**/
Surface::~Surface()
{
	if( surface != NULL )
	{
		SDL_FreeSurface( surface );
	}
}

/**
* Accessor to the wrapped SDL_SURFACE.
* 
* @return The wrapped surface
**/
SDL_Surface* Surface::GetSurface()
{
	return surface;
}

/**
* Gets the surface's width
* 
* @return The surface's width or -1 if not loaded.
**/
int Surface::GetWidth()
{
	if( surface == NULL )
		return -1;
	
	return surface->w;
}

/**
* Gets the surface's height
* 
* @return The surface's height or -1 if not loaded.
**/
int Surface::GetHeight()
{
	if( surface == NULL )
		return -1;
	
	return surface->h;
}

/**
* Load's the resource from the given location
* 
* @param filename The filename
* @return Success
**/
bool Surface::LoadResource( string filename )
{
	//Attack directory
	string file;
	if( LINUX_FILESYSTEM )
		file += "/usr/share/xyne/";
	file += filename;
	
	//Temporary storage for the image that's loaded
    SDL_Surface* loadedImage = NULL;
    
    //Load the image
    loadedImage = IMG_Load( file.c_str() );
    
    //If nothing went wrong in loading the image
    if( loadedImage != NULL )
    {
        //Create an optimized image
        surface = SDL_DisplayFormatAlpha( loadedImage );
        
        //Free the old image
        SDL_FreeSurface( loadedImage );
        
        return true;
    }
    else return false;
}

/**
* Scales based on the given factor
* 
* @param factor The scaling factor
**/
void Surface::Scale( double factor )
{
	//Zoomed image
    SDL_Surface* zoomedImage = rotozoomSurface( surface, 0, factor, SMOOTHING_ON );
    
    if( zoomedImage != NULL )
    {
    	//Free the old image
    	SDL_FreeSurface( surface );
    	
    	//Set the zoomed surface as the current surface
    	surface = zoomedImage;
    }
}

/**
* Applies this surface to another surface
* 
* @param dest Destination surface
* @param x The X coordinate of the destination
* @param y The Y coordinate of the destination
**/
void Surface::Apply( Surface* dest, int x, int y )
{
	Apply( dest, 0, 0, GetWidth(), GetHeight(), x, y );
}

/**
* Applies this surface to another surface
* 
* @param dest Destination surface
* @param sourceX The X coordinate of the desired section
* @param sourceY The Y coordinate of the desired section
* @param sourceWidth The width of the desired section
* @param sourceHeight The height of the desired section
* @param destX The X coordinate of the destination
* @param destY The Y coordinate of the destination
**/
void Surface::Apply( Surface* dest, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int destX, int destY )
{
	//Source rectangle
	SDL_Rect source;
	source.x = sourceX;
	source.y = sourceY;
	source.w = sourceWidth;
	source.h = sourceHeight;
	
	//Make a temporary rectangle to hold the offsets
    SDL_Rect offset;
    
    //Give the offsets to the rectangle
    offset.x = destX;
    offset.y = destY;

    //Blit the surface
    SDL_BlitSurface( surface, &source, dest->GetSurface(), &offset );
}
